require 'jinx/helpers/collections'

require 'jinx/helpers/validation'

module CaTissue
  # The CollectionProtocolRegistration domain class.
  class CollectionProtocolRegistration
    # @quirk caTissue Bug #64: Some domain collection properties not initialized.
    #   Initialize consent_tier_responses if necessary. 
    #
    # @return [Java::JavaUtil::Set] the responses
    def consent_tier_responses
      getConsentTierResponseCollection or (self.consent_tier_responses = Java::JavaUtil::LinkedHashSet.new)
    end

    # Returns whether the consent available flag is equal to the String 'true'. This method converts
    # the caTissue String to a Boolean.
    def consent_available
      getIsConsentAvailable == 'true'
    end

    # Sets the consent available flag to the specified value. A Boolean value is converted to a String.
    def consent_available=(value)
      value = value.to_s if value
      setIsConsentAvailable(value)
    end

    # Sets the consent available flag to the specified value. An Integer value is converted to a String.
    def protocol_participant_identifier=(value)
      value = value.to_s if value
      setProtocolParticipantIdentifier(value)
    end

    add_attribute_aliases("consented?".to_sym => :is_consent_available, :protocol => :collection_protocol,
      :participant_identifier => :protocol_participant_identifier, :consent_responses => :consent_tier_responses)

    set_secondary_key_attributes(:collection_protocol, :protocol_participant_identifier)

    set_alternate_key_attributes(:collection_protocol, :participant)

    add_attribute_defaults(:activity_status => 'Active')

    add_mandatory_attributes(:registration_date)

    # The CPR-Protocol association is bi-directional.
    set_attribute_inverse(:collection_protocol, :collection_protocol_registrations)

    # The CPR-Participant association is bi-directional.
    set_attribute_inverse(:participant, :collection_protocol_registrations)

    # consent_tier_responses is a cascaded dependent but is not fetched
    add_dependent_attribute(:consent_tier_responses, :unfetched)

    add_dependent_attribute(:specimen_collection_groups, :logical, :autogenerated)

    qualify_attribute(:collection_protocol, :fetched)

    qualify_attribute(:participant, :fetched)

    # CPR participant is part of the secondary key if it exists, but is optional. At least one
    # of the participant or PPI must exist. This is checked in the special purpose {#validate_local} method.
    qualify_attribute(:participant, :optional)

    # CPR PPI is part of the alternate key if it exists, but is optional. At least one of the participant or PPI
    # must exist. This is checked in the special purpose {#validate_local} method.
    qualify_attribute(:protocol_participant_identifier, :optional)

    # @quirk caTissue Augment the standard metadata savable reference attributes to work around caTissue Bug #150:
    #   Create CollectionProtocol in API ignores startDate.
    qualify_attribute(:registration_date, :update_only)

    # @quirk caTissue Bug #64 - consent tier responses is is not initialized to an empty set
    #    in the Java constructor. Initialize it to a +LinkedHashSet+ in caRuby.
    def initialize
      super
      # @quirk JRuby consent_tier_responses property method is not accessible until respond_to? is called.
      respond_to?(:consent_tier_responses)
      # work around caTissue Bug #64
      self.consent_tier_responses ||= Java::JavaUtil::LinkedHashSet.new
    end

    # Removes associations to this registration
    def delete
      participant.collection_registrations.delete(self) if participant
      protocol.registrations.delete(self) if protocol
    end

    # @return all specimens collected for this CollectionProtocolRegistration
    def specimens
      Jinx::Flattener.new(specimen_collection_groups.map { |scg| scg.specimens })
    end

    private

    def validate_local
      super
      if participant.nil? and protocol_participant_identifier.nil? then
        raise Jinx::ValidationError.new("#{qp} requires a participant or a protocol participant identifier.")
      end
    end
    
    # Adds defaults as follows:
    # * The default registration date is the current time.
    # * The default PPI is a unique number.
    def add_defaults_local
      super
      self.registration_date ||= Java.now
      self.protocol_participant_identifier ||= Jinx::UID.generate.to_s
    end
  end
end